// ====== Computer Graphics Experiment #5 ======
// |       Two-Dimensional Transformation      |
// =============================================
//
// Requirement:
// (1) Implement functions to generate 2D transformation matrix.
// (2) Implement function to transform 2D point using 
//     transformation matrix.
// (3) Implement functions to rotate, scale and translate objects 
//     using keyboard.

#include <windows.h>
#include <GL/glut.h>
#include <math.h>

#define PI 3.1415926535
// 2D point class
class CPoint2D
{
public:
	float x, y;
};

// 2D transformation matrix
float My2DMatrix[3][3];

// Generate translation matrix
void TranslationMatrix(float tx, float ty, float M[3][3])
// tx, ty --- Translation vector
{
		// Write your code here
}

// Generate rotation matrix
void RotationMatrix(float theta, float M[3][3])
// theta --- Rotation angle in degree
{
	// Write your code here
}

// Generate scaling matrix
void ScalingMatrix(float sx, float sy, float M[3][3])
// sx, sy --- Scaling factors
{
	// Write your code here
}


// Translate
void Translate(float tx, float ty)
// tx, ty --- Translation vector
{
	float M[3][3];
	TranslationMatrix(tx, ty, M);

	// Write your code here
	// Multiply M to the left of My2DMatrix
}

// Rotate
void Rotate(float theta)
// theta --- Rotation angle in degree
{
	float M[3][3];
	RotationMatrix(theta,M);
	// Write your code here
	// Multiply M to the left of My2DMatrix
}

// Scale
void Scale(float sx, float sy)
// sx, sy --- Scaling factors
{
	float M[3][3];
	ScalingMatrix(sx, sy, M);
	// Write your code here
	// Multiply M to the left of My2DMatrix
}

// Transform 2D point
void Transform2DPoint(CPoint2D *p, float M[3][3], CPoint2D *q)
// p --- Input point
// M --- Transformation matrix
// q --- Output point
{
	// Write your code here
}

void IdentityMatrix(float M[3][3])
{
  // Write your code here
}

// Initialization function
void init(void)
{
	glClearColor (0.0, 0.0, 0.5, 0.0);
	IdentityMatrix(My2DMatrix);
}

// Display callback function
void display(void)
{
	static CPoint2D MyObject[]=
	{{0.0, 63.0}, 
	{-60.0, 20.0}, {-60.0, -20.0}, 
	{60.0, -20.0}, {60.0, 20.0}};
	CPoint2D pp;
	int i;

	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 0.0, 0.0);

	glBegin(GL_POLYGON);
	for (i=0; i<5; ++i)
	{
		Transform2DPoint(MyObject+i, My2DMatrix, &pp);
		glVertex2f(pp.x, pp.y);
	}
	glEnd();

	glutSwapBuffers();
}

// Reshape callback function
void reshape(int w, int h)
{
	glViewport (0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-100, 100, -100, 100);
}



// Keyboard callback function
void keyboard(unsigned char key, int x, int y)
{
	switch (key) {
		case 27: exit(0);
	}
}

// Special keyboard callback function
void special_key(int key, int x, int y)
{
	switch (key) {
		case GLUT_KEY_LEFT:
			Translate(-5.0, 0.0);glutPostRedisplay();
			break;
		case GLUT_KEY_RIGHT:
			Translate(5.0, 0.0);glutPostRedisplay();
			break;
		case GLUT_KEY_DOWN:
			Translate(0.0, -5.0);glutPostRedisplay();
			break;
		case GLUT_KEY_UP:
			Translate(0.0, 5.0);glutPostRedisplay();
			break;
	// Add your code for rotation and scaling 
        case GLUT_KEY_PAGE_UP:

        case GLUT_KEY_PAGE_DOWN:

        case GLUT_KEY_HOME:

        case GLUT_KEY_END:

        case GLUT_KEY_INSERT:

	}
}

// Main program entrance
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize (500, 500);
	glutInitWindowPosition (100, 100);
	glutCreateWindow ("Test 2D Transformation");
	init ();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutSpecialFunc(special_key);
	glutMainLoop();
	return 0;
}
